package cn.edu.sjtu.flaw_detection.service.impl;

import cn.edu.sjtu.flaw_detection.dto.StateDTO;
import cn.edu.sjtu.flaw_detection.dto.TaskDTO;
import cn.edu.sjtu.flaw_detection.enums.ECNStateEnum;
import cn.edu.sjtu.flaw_detection.enums.TaskStateEnum;
import cn.edu.sjtu.flaw_detection.service.FlawDetectionService;
import cn.edu.sjtu.flaw_detection.util.TaskUtil;
import cn.edu.sjtu.flaw_detection.vo.TaskVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

@Service("mock")
@Slf4j
public class FlawDetectionServiceMockImpl implements FlawDetectionService {

  // 任务池
  // 存储所有任务，排队、正在执行的任务，和已经执行完的任务
  // 已经执行完的任务，再查询一次状态后删除
  private Map<String, TaskVO> tasksPool = new ConcurrentHashMap<>();

  @Override
  public void addTaskToPool(TaskDTO taskDTO) {
    TaskVO taskVO = new TaskVO();
    BeanUtils.copyProperties(taskDTO, taskVO);
    taskVO.setStatus(TaskStateEnum.PENDING);
    taskVO.setReleaseTime(new Date());
    String key = TaskUtil.genKey(taskDTO);
    tasksPool.put(key, taskVO);
  }

  @Override
  public StateDTO queryECNState() {
    // 0 pending 1 executing
    // 如果状态排队和执行中的任务数为0，则为空闲 反之
    long count =
        tasksPool.values().stream()
            .filter(t -> t.getStatus().ordinal() == 0 || t.getStatus().ordinal() == 1)
            .count();
    if (count == 0) {
      // 直接设置为ready 未考虑idle状态
      return StateDTO.ofECNState(ECNStateEnum.READY);
    }
    return StateDTO.ofECNState(ECNStateEnum.BUSY);
  }

  @Override
  public StateDTO queryTaskState(String processId, String taskId) {
    String key = processId.concat(taskId);
    TaskVO taskVO = tasksPool.get(key);
    if (taskVO != null) {
      StateDTO stateDTO = StateDTO.ofTaskState(taskVO);
      // 能不能 remove
      //      if (taskVO.getState() == TaskStateEnum.DONE) {
      //        tasksPool.remove(key);
      //      }
      return stateDTO;
    }
    return null;
  }

  // 展示队列中的任务
  @Override
  public List<TaskVO> listTaskQueue() {
    return tasksPool.values().stream()
        .filter(taskVO -> taskVO.getStatus() == TaskStateEnum.PENDING)
        .sorted(Comparator.comparing(TaskVO::getReleaseTime))
        .collect(Collectors.toList());
  }

  @Override
  public Map<Integer, List<TaskVO>> retTasksPool() {
    return tasksPool.values().stream()
        .collect(
            Collectors.groupingBy(
                item -> item.getStatus().ordinal(), LinkedHashMap::new, Collectors.toList()));
  }

  @Override
  public boolean startTask(TaskDTO taskDTO) {
    String key = TaskUtil.genKey(taskDTO);
    TaskVO taskVO = tasksPool.get(key);
    boolean ret = TaskUtil.switchState(taskVO, TaskStateEnum.PENDING, TaskStateEnum.EXECUTING);
    if (!ret) return false;
    taskVO.setStartTime(new Date());
    return true;
  }

  @Override
  public boolean endTask(TaskDTO taskDTO) {
    String key = TaskUtil.genKey(taskDTO);
    TaskVO taskVO = tasksPool.get(key);
    boolean ret = TaskUtil.switchState(taskVO, TaskStateEnum.EXECUTING, TaskStateEnum.DONE);
    if (!ret) return false;
    taskVO.setEndTime(new Date());
    return true;
  }
}
